package com.dycong.common.common;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 *
 * @author yu
 * @date 16-1-28
 */
@Log4j
public class ApplicationConfig {

    @Setter
    String propertyFile;

    static Properties config;

    @PostConstruct
    public void init() {
        try {
            Properties properties = new Properties();
            properties.load(ApplicationConfig.class.getResourceAsStream(propertyFile));
            ApplicationConfig.config = properties;
        } catch (Throwable throwable) {
            throw new RuntimeException("init " + ApplicationConfig.class.getName() + " failed.", throwable);
        }
    }

    public static Optional<String> get(String key) {
        try {
            if (config == null) {
                return Optional.empty();
            }
            return Optional.ofNullable(config.getProperty(key));
        } catch (Throwable throwable) {
            log.debug("get property " + key + " failed: " + throwable.toString());
            log.trace("", throwable);
            return Optional.empty();
        }
    }


    /**
     * @param prefix
     * @return
     */
    public static Map<String, String> getMapStartsWith(String prefix) {
        return config.entrySet().stream()
                .filter(e -> ((String) e.getKey()).startsWith(prefix))
                .collect(Collectors.toMap(
                        e -> ((String) e.getKey()).substring(prefix.length()),
                        e -> (String) e.getValue()
                ));
    }

    /**
     * if get empty result, then return defaultValue
     *
     * @param key
     * @param defaultValue
     * @return
     */
    public static String getOr(String key, String defaultValue) {
        return get(key).orElse(defaultValue);
    }


    public static Object set(String key, String value) {
        return config.setProperty(key, value);
    }


    public static <T> Optional<T> getType(String key, Function<String, T> mapper) {
        try {
            return get(key).map(mapper);
        } catch (Throwable throwable) {
            log.warn("map value failed: " + mapper.toString());
            log.debug("", throwable);
            return Optional.empty();
        }
    }

    public static Optional<Integer> getInt(String key) {
        return getType(key, Integer::valueOf);
    }

    public static Optional<Boolean> getBoolean(String key) {
        return getType(key, Boolean::valueOf);
    }

    public static Optional<Long> getLong(String key) {
        return getType(key, Long::valueOf);
    }

    public static Optional<Double> getDouble(String key) {
        return getType(key, Double::valueOf);
    }

}
